package com.stormragetech.arthas.process.context;

import com.stormragetech.arthas.common.annotation.Mapping;
import com.stormragetech.arthas.common.util.ArthasUtil;
import com.stormragetech.arthas.process.factory.ActionWrapper;
import com.stormragetech.arthas.spring.SpringUtil;
import lombok.extern.log4j.Log4j2;
import org.springframework.context.ApplicationContext;

import javax.swing.*;
import java.lang.reflect.Method;
import java.util.*;
import java.util.function.Predicate;

/**
 * description: context base initializer
 *
 * @author: Xue Bin
 * @version: 1.0.0-SNAPSHOT
 */
@Log4j2
abstract class ActionContext {

    @SuppressWarnings("unchecked")
    Map<String, ActionWrapper<?>> wrapperMap(List<String> names) {

        // get the value of class whole name in package
        // set the value into list
        //
        List<String> list = new ArrayList<>();
        names.forEach(name -> ArthasUtil.findFilesInPackage(name, list));
        log.info("the class file list is {}", list);

        // init the action wrapper of the classes
        // set the value into the map
        //
        Map<String, ActionWrapper<?>> map = new HashMap<>();
        list.forEach((String entry) -> {
            try {
                Class clazz = Class.forName(entry);
                Method[] methods = clazz.getDeclaredMethods();
                if (null == methods || methods.length <= 0) {
                    return;
                }
                Predicate<Method> predicate = m -> (null == m || null == m.getAnnotation(Mapping.class)) ? false : true;
                Arrays.stream(methods).filter(predicate).forEach((Method method) -> {
                    try {
                        ActionWrapper wrapper = new ActionWrapper();
                        if (null != SpringUtil.getContext()) {
                            wrapper.setAction(SpringUtil.getBean(clazz));
                        } else {
                            wrapper.setAction(clazz.newInstance());
                        }
                        wrapper.setName(clazz.getName());
                        wrapper.setTarget(method.getAnnotation(Mapping.class).url());
                        wrapper.setType(method.getAnnotation(Mapping.class).method());
                        wrapper.setResponse(method.getAnnotation(Mapping.class).response());
                        wrapper.setMethod(method);
                        map.put(method.getAnnotation(Mapping.class).url(), wrapper);
                    } catch (Exception e) {
                        log.error("Server error!!! {}", e);
                    }
                });
            } catch (Exception e) {
                e.printStackTrace();
            }
        });
        return map;
    }

}
